package com.cyou.annals.util;

import java.io.IOException;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

import com.cyou.annals.bean.GameInfo;
import com.cyou.annals.bean.GameInfoList;
import com.cyou.annals.bean.News;
import com.cyou.annals.bean.NewsResults;
import com.cyou.annals.bean.TestTime;
import com.cyou.annals.config.AnnalsConfig;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.googlecode.jsonrpc4j.JsonRpcHttpClient;

/**
 * @Title: AnnalsClient.java
 * @Description: 编年史客户端
 * @Company : cyou
 * @author cuishijie
 * @date 2012-12-06 下午4:53:30
 * @version V1.0
 */
public class AnnalsClient {

	// 全局对象映射（线程安全）
	private static final ObjectMapper mapper = new ObjectMapper();

	// 不可创建本类实例
	private AnnalsClient() {
	}

	static {
		mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
		mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
	}

	/**
	 * 获取用户信息
	 * 
	 * @param uid
	 * @return
	 */
	public static String getMemberInfo(int uid) {
		HttpClient httpClient = new HttpClient("http://my.17173.com/snsapi", false, false);

		Map<String, Object> map = new HashMap<String, Object>();
		map.put("method", "Member.getMemberInfo");
		map.put("apikey", "annalsApiKey");
		map.put("ver", "alpha");
		map.put("uid", uid);
		map.put("returnstyle", "JSON");
		map.put("sessionkey", "defaultKey");
		map.put("infomark", 0x00000001);
		String res = "";

		try {
			res = httpClient.getString("", map);
		} catch (IOException e) {
			e.printStackTrace();
		}

		return res;
	}

	/**
	 * 获取游戏信息列表
	 * 
	 * @param isDebug 是否是测试环境
	 * @return List<GameInfo>
	 */
	public static List<GameInfo> getGameList(boolean isDebug) {
		if (isDebug == true) {
			// 返回测试数据
			return creatTestGameList();
		} else {
			// 返回php接口中的数据
			return AnnalsClient.getGameList();
		}
	}

	/**
	 * 随机获取新闻信息
	 * 
	 * @return
	 */
	public static News getRandomNews() {
		List<News> newsList = getNews();
		if (null != newsList && newsList.size() > 0) {
			Random rand = new Random();
			return newsList.get(rand.nextInt(newsList.size()));
		}
		return null;
	}

	/**
	 * 获取新闻信息列表
	 * 
	 * @return
	 */
	public static List<News> getNews() {
		HttpClient httpClient = new HttpClient("http://search.17173.com", false, false);
		Map<String, Object> paramMap = new HashMap<String, Object>();
		paramMap.put("index-name", "WEBPAGE");
		paramMap.put("expression", "newsChannel:'10009'&&newsKind:'174248'");
		paramMap.put("page-size", "10");
		paramMap.put("page-no", "1");
		paramMap.put("sort-reverse", "true");
		paramMap.put("sort-type", "DOC");
		try {
			String json = httpClient.getString("/web/search.do", paramMap);
			if (json == null || json.length() == 0) {
				return null;
			}
			NewsResults newsResults = mapper.readValue(json, NewsResults.class);
			return newsResults.getResults();

		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;

	}

	/**
	 * 获取游戏信息
	 * 
	 * @param gameClassId
	 *            游戏类型Id
	 * @param filter
	 *            过滤器,可根据 关键字(keywords),游戏画面(game_face),游戏类型(game_type)等过滤
	 * @param sort
	 *            排序,可根据更新时间(update_time)倒序(DESC)或正序(ASC)排序,多个字段用逗号分隔,例:
	 *            'updateTime:DESC',默认根据更新时间倒序排列
	 * @param pageSize
	 *            每页返回记录个数
	 * @param pageNo
	 *            起始页码
	 * @param fields
	 *            返回结果可选字段
	 * @return
	 */
	public static List<GameInfo> getGameList(int gameClassId,
			Map<String, String> filter, String sort, int pageSize, int pageNo,
			String[] fields) {

		GameInfoList gameInfoList = new GameInfoList();
		List<GameInfo> gameInfoListData = null;
		try {
			int connectionTimeoutMillis = Integer.parseInt(AnnalsConfig
					.getValue("connectionTimeoutMillis"));
			int readTimeoutMillis = connectionTimeoutMillis - 1000;
			gameInfoList = callJsonRpcHttpClient(
					AnnalsConfig.getValue("php.gameInfoURL"),
					connectionTimeoutMillis, readTimeoutMillis, "getGameList",
					new Object[] { gameClassId, filter, sort, pageSize, pageNo,
							fields }, GameInfoList.class);
			gameInfoListData = gameInfoList.getDataSet();
			if (null != gameInfoListData && gameInfoListData.size() > 0) {
				for (GameInfo gameInfo : gameInfoListData) {
					gameInfo.setImageTitle(gameInfo.getName());
					gameInfo.setFirstTestTime(getFirstTestTime(gameInfo
							.getTest_time()));
				}

			}
		} catch (Throwable e) {
			e.printStackTrace();
		}
		return gameInfoListData;
	}

	/**
	 * 获取游戏信息<br>
	 * 通过php接口调用真实数据
	 * 
	 * @return
	 */
	private static List<GameInfo> getGameList() {
		int gameClassId = 1;// 新游类型
		String[] fields = getFields();
		Map <String, String> filter=new  HashMap<String, String>() ;
		filter.put("status", "1");
		int pageSize = Integer.parseInt(AnnalsConfig.getValue("php.gameSize"));
		return getGameList(gameClassId, filter, null, pageSize, 0, fields);

	}

	/**
	 * 构造测试游戏信息 <br>
	 * （外网访问不倒php端口根据GameInfo构造数据）
	 * 
	 * @return List<GameInfo>
	 */
	private static List<GameInfo> creatTestGameList() {
		List<GameInfo> testGameList = new ArrayList<GameInfo>();

		// 测试数据1
		GameInfo gameInfo = new GameInfo();
		gameInfo.setShow_pic("http://i2.17173.itc.cn/2012/newgame/12/1010571077.jpg");
		gameInfo.setLogo_pic("http://i3.17173.itc.cn/2012/newgame/12/1010550164.jpg");
		gameInfo.setFirstTestTime("1355932800");
		gameInfo.setId("9690");
		gameInfo.setGame_code("12054");
		gameInfo.setName("完美西游");
		gameInfo.setAlias("");
		gameInfo.setIntroduction("《完美西游》是基于《仙尘OL》，由小说《西游记》故事为背景开发的奇幻网游。");
		gameInfo.setInitial("W");
		gameInfo.setPinyin("wmxy");
		gameInfo.setTags("");
		List<TestTime> time1 = new ArrayList<TestTime>();
		gameInfo.setTest_time(time1);
		gameInfo.setImageTitle("完美西游");
		gameInfo.setStatus("1");
		testGameList.add(gameInfo);

		// 测试数据2
		GameInfo gameInfo2 = new GameInfo();
		gameInfo2.setShow_pic("http://i3.17173.itc.cn/2012/newgame/12/0318140867.jpg");
		gameInfo2.setLogo_pic("http://i1.17173.itc.cn/2012/newgame/12/0318140181.jpg");
		gameInfo2.setFirstTestTime("1355932800");
		gameInfo2.setId("9688");
		gameInfo2.setGame_code("12053");
		gameInfo2.setName("FreeStyle2");
		gameInfo2.setAlias("FreeStyle2");
		gameInfo2.setIntroduction("《FreeStyle2》是韩国JCE开发的《街头篮球》的正统续作，目前国服代理确定为世纪天成。");
		gameInfo2.setInitial("F");
		gameInfo2.setPinyin("jtlq");
		gameInfo2.setTags("街头篮球|街头篮球2");
		List<TestTime> time2 = new ArrayList<TestTime>();
		gameInfo2.setTest_time(time2);
		gameInfo2.setImageTitle("FreeStyle2");
		gameInfo2.setStatus("1");
		testGameList.add(gameInfo2);

		return testGameList;
	}

	/**
	 * 调用JsonRpcHttpClient
	 * 
	 * @param <T>
	 * @param url
	 * @param connectionTimeoutMillis
	 * @param method
	 * @param param
	 * @param clz
	 * @return
	 * @throws Throwable
	 */
	private static <T> T callJsonRpcHttpClient(String url,
			int connectionTimeoutMillis, int readTimeoutMillis, String method,
			Object[] param, Class<T> clz) throws Throwable {
		JsonRpcHttpClient client = new JsonRpcHttpClient(new URL(url));
		client.setConnectionTimeoutMillis(connectionTimeoutMillis);
		client.setReadTimeoutMillis(readTimeoutMillis);
		return client.invoke(method, param, clz);
	}

	/**
	 * 获取查询字段
	 * 
	 * @return
	 */
	private static String[] getFields() {
		return new String[] { "id", "name", "alias", "game_code", "pinyin",
				"initial", "tags", "test_time", "logo_pic", "show_pic",
				"recommend"};
	}

	/**
	 * 对测试时间排序,获取最早的测试时间
	 * 
	 * @param testTimeList
	 * @return
	 */
	private static String getFirstTestTime(List<TestTime> testTimeList) {
		class ComparatorTestTime implements Comparator<TestTime> {
			@Override
			public int compare(TestTime o1, TestTime o2) {
				return o1.getDatetime().compareTo(o2.getDatetime());
			}
		}
		if (null != testTimeList && testTimeList.size() > 0) {
			Comparator<TestTime> comparator = new ComparatorTestTime();
			Collections.sort(testTimeList, comparator);
			return testTimeList.get(0).getDatetime();

		}
		return "";
	}
}
